package  core.managers
{
	import com.greensock.TweenLite;
	
	import core.display.panel.BasePanel;
	import core.display.panel.BaseTool;
	import core.display.panel.BaseWindow;
	import core.events.GlobalEvent;
	import core.events.GlobalEventDispatcher;
	
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.geom.Point;
	
	import good.drag.IRoot;
	
	import newbie.parser.ParserMain;
	import core.consts.PanelTypes;

	/**
	 * 面板管理的工具类，包含了各层容器的引用，舞台的高度，新手引导编辑器的引用，添加面板，移除面板，面板的缓动效果，清空容器等。
	 * 但是，如果你想使用这个类，那么，请在主容器里面一定要加上PanelManager.init(this)或者PanelManager.init(this.stage)。
	 * @author Ado
	 **/
	public class PanelManager
	{
		/**
		 * 全局舞台 
		 */		
		public static var stage:Stage;
		/** 根对象，实现IRoot的原因是为了实现对item的拖放 */
		public static var root:IRoot;
		
		private static var _mapContainer:Sprite;
		private static var _buildingContainer:Sprite;
		private static var _roleContainer:Sprite;
		private static var _sceneToolsContainer:Sprite;
		private static var _panelContainer:Sprite;
		private static var _alertContainer:Sprite;
		/**
		 * 新手引导容器 
		 */		
		public static var newbieContainer:Sprite;
		/**
		 * 全局宽度 ：与stage.stageWidth保持一致
		 */		
		public static var GlobalWidth:Number;
		/**
		 * 全局高度 ：与stage.stageHeight保持一致
		 */		
		public static var GlobalHeight:Number;
		/**
		 *  新手引导解析器
		 */		
		public static var newbieParser:ParserMain;
		public function PanelManager()
		{
		}
		/**
		 * 初始化游戏里面的各容器，在初始化游戏的时候在主程序里面调用一次就可以了
		 * @param s 舞台或者主程序本身
		 * @throw Error root is not fitted.
		 */		
		public static function init(s:Object):void
		{
			if(stage || root) 
			{
				throw new Error("PanelManager has been initialized already.");
			}
			if(s is Stage)
			{
				stage = s as Stage;
			}else if(s is IRoot){
				root = s as IRoot;
			}else
			{
				throw new Error("PanelManager.init(root): root is not fitted...");
			}
			
			_mapContainer = new Sprite();
			s.addChild(_mapContainer);
			
			_buildingContainer = new Sprite();
			s.addChild(_buildingContainer);
			
			_roleContainer = new Sprite();
			s.addChild(_roleContainer);
			
			_sceneToolsContainer = new Sprite();
			s.addChild(_sceneToolsContainer);
			
			_panelContainer = new Sprite();
			s.addChild(_panelContainer);
			
			_alertContainer = new Sprite();
			s.addChild(_alertContainer);
			
			newbieContainer = new Sprite();
			s.addChild(newbieContainer);
			//排除其他所有面板
			GlobalEventDispatcher.getInstance().addEventListener(GlobalEvent.EXLUDE_PANELS, excludePanels);
		}
		
		/**
		 * 移除当前面板 
		 * @param panel
		 * 
		 */		
		public static function removePanel(panel:BasePanel):void
		{
			if(panel.parent == null) return;
			panel.parent.removeChild(panel);
			if(panel.panelType == PanelTypes.SHARE)
			{
				resort();
			}else if(panel.panelType == PanelTypes.MONOPOLIZE)
			{
				checkEnable(true);
			}
		}
		
		/**
		 * 往舞台上添加面板，根据面板类型，会选择不同的容器 
		 * @param panel
		 * 
		 */		
		public static function addPanel(panel:BasePanel):void
		{
			if(panel.panelType == PanelTypes.SHARE){
				//共存类型面板添加到舞台之后要重排所有其他面板
				_panelContainer.addChild(panel);
				if(panel is BaseWindow)
				{
					panel.y = (GlobalHeight - panel.height)/2;
					panel.x = (GlobalWidth - panel.width)/2;
					resort();
				}
			}else if(panel.panelType == PanelTypes.EXCLUDE)
			{
				//独占类型的面板要清空容器里面的面板
				clearContainer(_panelContainer);
				_panelContainer.addChild(panel);
			}else{
				//排斥面板是在alertContainer里面显示
				panel.y = (GlobalHeight - panel.height)/2;
				panel.x = (GlobalWidth - panel.width)/2;
				clearContainer(_alertContainer);
				_alertContainer.addChild(panel);
				checkEnable(false);
			}
		}
		/** 类型为排除的面板显示的时候发出的事件的处理器 */
		private static function excludePanels(e:GlobalEvent):void
		{
			var windows:Array = getWindows();
			for each(var w:BaseWindow in windows)
			{
				w.setAllCloseVisual(false);
				removePanel(w);
			}
		}
		/**
		 * 重新排列所有面板 
		 * 
		 */		
		private static function resort():void
		{
			var windows:Array = getWindows();
			var totalWidth:Number = getTotalWidth(windows);
			windows.sortOn("x");
			var targetX:Number = (GlobalWidth-totalWidth)/2;
			for(var i:int=0; i<windows.length;i++)
			{
				var offset:Point = new Point(targetX-windows[i].x,(GlobalHeight-windows[i]["height"])/2-windows[i].y);
				TweenLite.to(
					windows[i],
					1,
					{x:targetX,
					y:(GlobalHeight-windows[i]["height"])/2,
					onComplete:easeComplete,
					onCompleteParams:[windows[i]],
					onUpdate :onTweenUpdate,
					onUpdateParams:[windows[i],new Point(windows[i].x,windows[i].y)]}
				);
				
				targetX += windows[i].width;
			}
			var visual:Boolean = windows.length > 1;
			for each(var w:BaseWindow in windows)
			{
				w.setAllCloseVisual(visual);
			}
		}
		/** 面板的缓动效果完成之后的事件处理器 */
		private static function onTweenUpdate(sp:Sprite, refer:Point):void
		{
			var window:BaseWindow = sp as BaseWindow;
			window.offset = new Point(window.x- refer.x, window.y-refer.y);
		}
		/**
		 * 缓动结束后的处理函数 
		 * @param param_sp
		 * 
		 */		
		private static function easeComplete(param_sp:Sprite):void
		{
			TweenLite.killTweensOf(param_sp);
		}
		/**
		 * 清空容器 
		 * @param con
		 * 
		 */		
		private static function clearContainer(con:Sprite):void
		{
			var len:int = con.numChildren;
			while(len>0)
			{
				var panel:BaseWindow = con.getChildAt(len-1) as BaseWindow;
				if(panel) panel.hide();
				len--;
			}
		}
		/**
		 * 将除alertContainer以外的容器的鼠标事件全部清除 
		 * @param enable
		 * 
		 */		
		private static function checkEnable(enable:Boolean):void
		{
			_mapContainer.mouseChildren = enable;
			_mapContainer.mouseEnabled = enable;
			
			_buildingContainer.mouseChildren = enable;
			_buildingContainer.mouseEnabled = enable;
			
			_roleContainer.mouseChildren = enable;
			_roleContainer.mouseEnabled = enable;
			
			_panelContainer.mouseChildren = enable;
			_panelContainer.mouseEnabled = enable;
		}
		/**
		 * 取得当前所有面板总宽度 
		 * @param arr
		 * @return 
		 * 
		 */		
		private static function getTotalWidth(arr:Array):Number
		{
			var width:Number = 0;
			for each(var i:Sprite in arr)
			{
				width += i.width;
			}
			return width;
		}
		/**
		 * 取得当前面板容器的所有面板 
		 * @return 
		 * 
		 */		
		private static function getWindows():Array
		{
			var len:int = _panelContainer.numChildren;
			var windows:Array = [];
			for(var i:int=len-1; i >= 0; i--)
			{
				var panel:BaseWindow = _panelContainer.getChildAt(i) as BaseWindow;
				if(panel)
				{
					if(panel.panelType == PanelTypes.EXCLUDE)//如果有独占类型窗口的话隐藏之
					{
						panel.hide();
					}else
					{
						windows.push(panel);
					}
				}
			}
			return windows;
		}

		/**
		 * 地图容器 :最底层，用来放地图元素
		 */
		public static function get mapContainer():Sprite
		{
			return _mapContainer;
		}

		/**
		 * 建筑容器 ：倒数第二层，用来放置建筑元素
		 */
		public static function get buildingContainer():Sprite
		{
			return _buildingContainer;
		}

		/**
		 * 角色容器 ：倒数第三层，用来放置玩家，NPC，怪物
		 */
		public static function get roleContainer():Sprite
		{
			return _roleContainer;
		}

		/**
		 * 面板容器 ：倒数第五层，用来放置面板
		 */
		public static function get panelContainer():Sprite
		{
			return _panelContainer;
		}

		/**
		 * 警告容器：警告框与新手引导的容器
		 */
		public static function get alertContainer():Sprite
		{
			return _alertContainer;
		}

		/**
		 * 固定面板容器 ：倒数第四层，用来放固定面板
		 */
		public static function get sceneToolsContainer():Sprite
		{
			return _sceneToolsContainer;
		}
	}
}